#include <stdexcept>

// Constructors
Day::Day(void) :
   m_enum(sunday),
   m_string("Sunday"),
   m_value(0)
{}

Day::Day(Enum _e) :
   m_enum(_e),
   m_string(toString(_e)),
   m_value(0)
{}

Day::Day(const std::string& _s) :
   m_enum(fromString(_s)),
   m_string(_s),
   m_value(toValue(m_enum))
{}

// Assignment operators

Day& Day::operator= (const Day& _c)
{
   m_string = _c.m_string;
   m_enum   = _c.m_enum;
   m_value  = _c.m_value;
   return *this;
}

Day& Day::operator= (const std::string& _s)
{
   m_string = _s;
   m_enum   = fromString(_s);
   m_value  = toValue(m_enum);
   return *this;
}

Day& Day::operator= (Enum _e)
{
   m_enum   = _e;
   m_string = toString(_e);
   m_value  = toValue(_e);
   return *this;
}

bool Day::operator< (const Day& _c) const
{
   return (m_value < _c.m_value);
}

bool Day::operator< (Enum _e) const
{
   return (m_value < toValue(_e));
}

bool Day::operator<= (const Day& _c) const
{
   return (m_value <= _c.m_value);
}

bool Day::operator<= (Enum _e) const
{
   return (m_value <= toValue(_e));
}

bool Day::operator> (const Day& _c) const
{
   return (m_value > _c.m_value);
}

bool Day::operator> (Enum _e) const
{
   return (m_value > toValue(_e));
}

bool Day::operator>= (const Day& _c) const
{
   return (m_value >= _c.m_value);
}

bool Day::operator>= (Enum _e) const
{
   return (m_value >= toValue(_e));
}

bool Day::operator== (const Day& _c) const
{
   return (m_enum == _c.m_enum);
}

bool Day::operator== (const std::string& _s) const
{
   return (m_string == _s);
}

bool Day::operator== (const Enum _e) const
{
   return (m_enum == _e);
}

bool Day::operator!= (const Day& _c) const
{
   return (m_enum != _c.m_enum);
}

bool Day::operator!= (const std::string& _s) const
{
   return (m_string != _s);
}

bool Day::operator!= (const Enum _e) const
{
   return (m_enum != _e);
}

Day::Enum Day::fromString(std::string _s)
{
   // Case insensitive - make all upper case
   transform(_s.begin(), _s.end(), _s.begin(), toupper);
   if(_s == "SUNDAY")         return sunday;
   else if(_s == "MONDAY")    return monday;
   else if(_s == "TUESDAY")   return tuesday;
   else if(_s == "WEDNESDAY") return wednesday;
   else if(_s == "THURSDAY")  return thursday;
   else if(_s == "FRIDAY")    return friday;
   else if(_s == "SATURDAY")  return saturday;

   throw std::range_error("Not a valid Day value: " + _s);
   return InvalidDay;
};

std::string Day::toString(Day::Enum _e)
{
   switch (_e)
   {
      case sunday:    { return "SUNDAY";    }
      case monday:    { return "MONDAY";    }
      case tuesday:   { return "TUESDAY";   }
      case wednesday: { return "WEDNESDAY"; }
      case thursday:  { return "THURSDAY";  }
      case friday:    { return "FRIDAY";    }
      case saturday:  { return "SATURDAY";  }
   }
   return "InvalidDay";
}

int Day::toValue(Day::Enum _e)
{
   switch (_e)
   {
      case sunday:    { return 0; }
      case monday:    { return 2; }
      case tuesday:   { return 3; }
      case wednesday: { return 4; }
      case thursday:  { return 5; }
      case friday:    { return 6; }
      case saturday:  { return 7; }
   }
   return 8;  // Invalid
}
